package org.wevil.util;

import org.wevil.entity.sys.SysUser;
import org.wevil.props.LoginProp;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * jwt 工具类
 *
 * @author 李南广
 */
public class JwtUtil {

    /** 生成web端 token */
    public static String getToken(SysUser sysUser){
        LoginProp prop = BeanUtil.getBean(LoginProp.class);
        String secret = prop.getSecret();
        Long outTime = prop.getOutTime();
        Integer userId = sysUser.getId();
        Map<String, Integer> maps = new HashMap<>(1);
        maps.put("userId", userId);
        return JwtUtil.create(maps, secret, outTime);
    }

    /** 获取token里的userId */
    public static Integer getUserId(String token) {
        Map<String, Claim> claimMap = JwtUtil.verifyToken(token);
        return claimMap.get("userId").asInt();
    }

    /**
     * 创建token
     *
     * @param claims  存放在token中的信息
     * @param secret  秘钥
     * @param outTime 过期时间单位秒
     */
    public static String create(Map<String, Integer> claims, String secret, long outTime) {
        try {
            Date expirationTime = new Date(System.currentTimeMillis() + outTime * 1000);
            Algorithm algorithm = Algorithm.HMAC256(secret);
            Map<String, Object> headerMap = new HashMap<>(2);
            headerMap.put("type", "JWT");
            headerMap.put("alg", "HS256");
            JWTCreator.Builder builder = JWT.create().withHeader(headerMap);
            for (String key : claims.keySet()) {
                builder.withClaim(key, claims.get(key));
            }
            return builder.withExpiresAt(expirationTime).sign(algorithm);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 校验jwt 合法性 返回claims
     *
     * @param token 秘钥
     * @throws JWTDecodeException       token 解码失败
     * @throws IllegalArgumentException token格式不正确不是 aaa.bbb.ccc
     * @throws TokenExpiredException    token超时
     */
    public static Map<String, Claim> verifyToken(String token) throws JWTDecodeException, IllegalArgumentException, TokenExpiredException {
        LoginProp prop = BeanUtil.getBean(LoginProp.class);
        String secret = prop.getSecret();
        DecodedJWT decodedJWT;
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret)).build();
        decodedJWT = verifier.verify(token);
        return decodedJWT.getClaims();
    }

    /**
     * 校验jwt 合法性 返回claims
     *
     * @param token 秘钥
     * @throws JWTDecodeException       token 解码失败
     * @throws IllegalArgumentException token格式不正确不是 aaa.bbb.ccc
     * @throws TokenExpiredException    token超时
     */
    public static Map<String, Claim> verifyToken(String token, String secret) throws JWTDecodeException, IllegalArgumentException, TokenExpiredException {
        DecodedJWT decodedJWT;
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret)).build();
        decodedJWT = verifier.verify(token);
        return decodedJWT.getClaims();
    }
}
